import 'dart:async';
import 'dart:convert';
import 'dart:ui' as ui;
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_base/amap_flutter_base.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:xiaofanshu_flutter/static/custom_code.dart';
import 'package:xiaofanshu_flutter/config/amap_config.dart';
import 'package:xiaofanshu_flutter/model/response.dart';
import 'package:xiaofanshu_flutter/apis/app.dart';
import 'package:xiaofanshu_flutter/utils/store_util.dart';
import 'package:xiaofanshu_flutter/static/default_data.dart';
import 'package:xiaofanshu_flutter/model/user.dart';

class StoryMapPubController extends GetxController {
  // 地图相关
  var currentZoom = 15.0.obs;
  var clusterThreshold = 13.0.obs;
  var showFilterPopup = false.obs;
  var showStoryPreview = false.obs;
  var currentStoryIndex = 0.obs;
  var isLocationInitialized = false.obs;
  var hasMovedToLocation = false.obs;
  
  // 聚合相关参数
  var currentBounds = Rx<Map<String, double>?>(null); // 当前地图边界
  var isClusterMode = false.obs; // 是否处于聚合模式
  static const double clusterZoomThreshold = 13.0; // 聚合模式缩放阈值
  Timer? _loadDataTimer; // 防抖定时器
  
  // 高德地图相关
  AMapController? mapController;
  AMapFlutterLocation? locationPlugin;
  StreamSubscription<Map<String, Object>>? locationSubscription;
  var currentLocation = Rxn<LatLng>();
  var cameraPosition = Rxn<CameraPosition>();
  var markers = <Marker>[].obs;
  var isInitComplete = false.obs;  // 初始化完成标志位

  // 故事钉数据
  var storyPins = <StoryPin>[].obs;
  var filteredPins = <StoryPin>[].obs;

  // 分类数据
  var categories = <Map<String, dynamic>>[].obs; // 存储从API获取的分类数据
  var selectedCategories = <String, bool>{}.obs; // 动态生成的选中状态
  var showOfficialOnly = false.obs;
  
  // 用户筛选
  var nicknameFilter = ''.obs;
  
  // 选择地点模式
  var isSelectLocationMode = false.obs;
  var selectedLocation = Rxn<LatLng>();
  var selectedLocationAddress = ''.obs;
  
  // 路线创建模式
  var isRouteCreationMode = true.obs; // 默认为路线创建模式
  var routeMarkers = <LatLng>[].obs; // 存储路线中的marker位置
  var selectedMarkerIndex = (-1).obs; // 当前选中的marker索引
  var routeName = ''.obs; // 路线名称
  var maxMarkers = 10; // 最多10个marker
  var routeLines = <Polyline>[].obs; // 存储路线连线
  
  // 故事marker连接功能
  var isStoryConnectionMode = false.obs; // 是否处于故事连接模式
  var connectedStoryPins = <StoryPin>[].obs; // 已连接的故事marker序列
  var maxConnectedStories = 10; // 最多连接10个故事

  @override
  void onInit() {
    super.onInit();
    // 异步初始化定位，不阻塞UI
    _initLocation();
    
    // 监听路线markers变化，自动更新显示
    ever(routeMarkers, (_) => updateRouteMarkers());
    ever(selectedMarkerIndex, (_) => updateRouteMarkers());
  }

  @override
  void onClose() {
    _loadDataTimer?.cancel();
    locationSubscription?.cancel();
    locationPlugin?.destroy();
    super.onClose();
  }

  Future<void> _initLocation() async {
    Get.log('StoryMapController开始初始化定位');
    
    // 设置API密钥
    AMapFlutterLocation.setApiKey(AMapConfig.androidKey, AMapConfig.iosKey);
    Get.log('API密钥已设置');
    
    // 设置隐私合规
    AMapFlutterLocation.updatePrivacyShow(true, true);
    AMapFlutterLocation.updatePrivacyAgree(true);
    Get.log('隐私合规已设置');
    
    // 请求定位权限
    bool hasPermission = await requestLocationPermission();
    Get.log('定位权限请求结果: $hasPermission');
    
    if (!hasPermission) {
      Get.log('定位权限未授予，使用默认位置');
      isLocationInitialized.value = true;
      return;
    }
    
    // 实例化定位插件 - 参考LocationController的实现
    locationPlugin = AMapFlutterLocation();
    Get.log('定位插件已实例化');
    
    // 设置定位监听 - 参考LocationController的实现，先设置监听
    locationSubscription = locationPlugin!.onLocationChanged().listen((Map<String, Object> result) async {
      Get.log('收到定位回调: $result');
      
      // 如果已经移动过，则直接返回
      if (hasMovedToLocation.value) {
        Get.log('已经移动过地图，跳过处理');
        return;
      }
      
      try {
        // 检查是否有有效的位置数据
        if (result['latitude'] == null || result['longitude'] == null) {
          Get.log('定位数据无效: lat=${result['latitude']}, lng=${result['longitude']}');
          return;
        }
        
        double lat = double.parse(result['latitude'].toString());
        double lng = double.parse(result['longitude'].toString());
        
        // 检查是否为0.0,0.0的无效位置
        if (lat == 0.0 && lng == 0.0) {
          Get.log('收到无效位置 (0.0, 0.0)，跳过处理');
          return;
        }
        
        currentLocation.value = LatLng(lat, lng);
        cameraPosition.value = CameraPosition(
          target: currentLocation.value!,
          zoom: currentZoom.value,
        );
        Get.log('当前位置更新为: ${currentLocation.value}');
        
        // 只在第一次获取到有效位置时移动地图
        if (mapController != null && currentLocation.value != null) {
          mapController?.moveCamera(
            CameraUpdate.newLatLngZoom(currentLocation.value!, currentZoom.value),
          );
          hasMovedToLocation.value = true;
          Get.log('地图已移动到当前位置');
        } else {
          // mapController还未初始化，记录位置待后续使用
          Get.log('mapController还未初始化，位置数据已保存，待地图初始化后自动移动');
          // 此时不设置hasMovedToLocation，保持为false，待地图初始化后自动移动
        }
      } catch (e) {
        Get.log('处理定位结果出错: $e');
      }
    });
    
    Get.log('定位监听已设置');
    
    // 设置定位参数 - 在设置监听之后，参考LocationController的实现
    _setLocationOption();
    Get.log('定位参数已设置');
    
    isLocationInitialized.value = true;
    
    // 开始定位 - 参考LocationController的实现
    try {
      locationPlugin?.startLocation();
      Get.log('开始定位');
    } catch (e) {
      Get.log('启动定位服务出错: $e，使用默认位置');
      // 如果启动失败，使用默认位置
      currentLocation.value = LatLng(39.9042, 116.4074); // 北京天安门
      cameraPosition.value = CameraPosition(
        target: currentLocation.value!,
        zoom: currentZoom.value,
      );
      isLocationInitialized.value = true;
      isInitComplete.value = true;
      await _loadInitialData();
    }
    
    // 标记初始化完成
    isInitComplete.value = true;
    Get.log('定位初始化完成，isInitComplete=${isInitComplete.value}');
    
    // 初始化完成后加载数据
    await _loadInitialData();
  }
  
  // 请求定位权限
  Future<bool> requestLocationPermission() async {
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      return true;
    } else {
      status = await Permission.location.request();
      return status == PermissionStatus.granted;
    }
  }

  // 设置定位参数 - 参考LocationController的实现
  void _setLocationOption() {
    AMapLocationOption locationOption = AMapLocationOption();

    ///是否单次定位
    locationOption.onceLocation = true; // 单次定位获取当前位置

    ///是否需要返回逆地理信息
    locationOption.needAddress = true;

    ///逆地理信息的语言类型
    locationOption.geoLanguage = GeoLanguage.DEFAULT;

    locationOption.desiredLocationAccuracyAuthorizationMode =
        AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;

    locationOption.fullAccuracyPurposeKey = "AMapLocationScene";

    ///设置Android端连续定位的定位间隔
    locationOption.locationInterval = 2000;

    ///设置Android端的定位模式<br>
    ///可选值：<br>
    ///<li>[AMapLocationMode.Battery_Saving]</li>
    ///<li>[AMapLocationMode.Device_Sensors]</li>
    ///<li>[AMapLocationMode.Height_Accuracy]</li>
    locationOption.locationMode = AMapLocationMode.Hight_Accuracy;

    ///设置iOS端的定位最小更新距离<br>
    locationOption.distanceFilter = -1;

    ///设置iOS端期望的定位精度
    /// 可选值：<br>
    /// <li>[DesiredAccuracy.Best] 最高精度</li>
    /// <li>[DesiredAccuratForNavigation] 适用于导航场景的高精度 </li>
    /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
    /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
    /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
    locationOption.desiredAccuracy = DesiredAccuracy.Best;

    ///设置iOS端是否允许系统暂停定位
    locationOption.pausesLocationUpdatesAutomatically = false;

    ///将定位参数设置给定位插件
    locationPlugin!.setLocationOption(locationOption);
  }

  // Future<void> _loadStoryPins() async {
  //   try {
  //     // 模拟从后端获取数据
  //     // 实际项目中应该调用API获取真实数据
  //     // var response = await Request.get('/story/pins');
  //     // if (response.statusCode == 200) {
  //     //   var data = ResponseModel.fromJson(json.decode(response.body));
  //     //   if (data.code == 200) {
  //     //     // 解析故事钉数据
  //     //     storyPins.value = _parseStoryPins(data.data);
  //     //     _updateFilteredPins();
  //     //     _updateMarkers();
  //     //   }
  //     // } else {
  //     //   // 使用模拟数据
  //     //   _loadMockData();
  //     // }
      
  //     // 暂时使用模拟数据
  //     _loadMockData();
  //   } catch (e) {
  //     // 使用模拟数据
  //     _loadMockData();
  //   }
  // }

  Future<void> _loadMockData() async {
    storyPins.value = [
      StoryPin(
        id: '1',
        title: '这家隐藏咖啡馆也太可了吧！',
        content: '偶然发现的小众咖啡馆，环境超级温馨，墙上全是复古装饰，每个角落都很适合拍照，重点是他家的脏脏包真的绝了！松软的面包...',
        lat: 39.9042,
        lng: 116.4074,
        type: 'coffee',
        noteType: 0,
        isOfficial: true,
        imageUrls: [
          'https://example.com/coffee1.jpg',
          'https://example.com/coffee2.jpg',
          'https://example.com/coffee3.jpg',
        ],
        author: '小红薯123',
        likes: 2300,
      ),
      StoryPin(
        id: '2',
        title: '北京胡同里的秘密花园',
        content: '藏在老胡同里的小花园，种满了各种花草，阳光洒下来的时候特别美，简直是城市中的世外桃源...',
        lat: 39.9142,
        lng: 116.4274,
        type: 'travel',
        noteType: 0,
        isOfficial: false,
        imageUrls: [
          'https://example.com/garden1.jpg',
        ],
        author: '摄影师小王',
        likes: 1500,
      ),
      StoryPin(
        id: '3',
        title: '深夜食堂推荐',
        content: '这家深夜食堂的拉面真的绝了！汤底浓郁，叉烧入口即化，每次加班后必来打卡...',
        lat: 39.9242,
        lng: 116.3974,
        type: 'food',
        noteType: 0,
        isOfficial: true,
        imageUrls: [
          'https://example.com/ramen1.jpg',
          'https://example.com/ramen2.jpg',
        ],
        author: '美食达人',
        likes: 3200,
      ),
    ];
    // _updateFilteredPins();
    await updateMarkers();
  }

  List<StoryPin> _parseStoryPins(dynamic data) {
    // 实际项目中解析后端返回的故事钉数据
    return [];
  }

  // void _updateFilteredPins() {
  //   filteredPins.value = storyPins.where((pin) {
  //     if (showOfficialOnly.value && !pin.isOfficial) return false;
  //
  //     // 将故事钉的类型转换为小写，与分类名称匹配
  //     String pinType = pin.type.toLowerCase();
  //
  //     // 检查是否有匹配的分类
  //     bool hasMatchingCategory = selectedCategories.containsKey(pinType) &&
  //                                (selectedCategories[pinType] ?? false);
  //
  //     // 如果没有直接匹配，尝试模糊匹配
  //     if (!hasMatchingCategory) {
  //       for (var category in categories) {
  //         String categoryName = category['categoryName']?.toString().toLowerCase() ?? '';
  //         if (categoryName.contains(pinType) || pinType.contains(categoryName)) {
  //           hasMatchingCategory = selectedCategories[categoryName] ?? false;
  //           break;
  //         }
  //       }
  //     }
  //
  //     return hasMatchingCategory;
  //   }).toList();
  // }

  Future<void> updateMarkers() async {
    markers.clear();
    List<Marker> newMarkers = [];
    
    for (var pin in filteredPins) {
      try {
        // 检查是否为已连接的故事
        bool isConnected = connectedStoryPins.any((p) => p.id == pin.id);
        
        // 异步创建图标
        BitmapDescriptor icon;
        if (isStoryConnectionMode.value && isConnected) {
          // 已连接的故事使用绿色标记
          icon = await _createConnectedStoryIcon(pin);
        } else {
          // 普通故事marker
          icon = await _createMarkerIcon(pin);
        }
        
        // 创建InfoWindow显示连接状态
        String snippet = '';
        if (isStoryConnectionMode.value) {
          if (isConnected) {
            int index = connectedStoryPins.indexWhere((p) => p.id == pin.id);
            snippet = '已连接 (第${index + 1}个)';
          } else {
            snippet = '点击连接';
          }
        }
        
        final marker = Marker(
          position: LatLng(pin.lat, pin.lng),
          icon: icon,
          infoWindow: InfoWindow(
            title: pin.title,
            snippet: isStoryConnectionMode.value ? snippet : '',
          ),
          onTap: (String id) => onMarkerTap(pin),
        );
        newMarkers.add(marker);
      } catch (e) {
        Get.log('创建标记失败: ${pin.id}, 错误: $e');
        // 如果创建失败，使用默认图标
        final marker = Marker(
          position: LatLng(pin.lat, pin.lng),
          icon: BitmapDescriptor.defaultMarker,
          onTap: (String id) => onMarkerTap(pin),
        );
        newMarkers.add(marker);
      }
    }
    
    markers.value = newMarkers;
  }

  // 处理地图移动事件，根据缩放级别决定调用哪个API
  void onCameraMove(CameraPosition cameraPosition) {
    currentZoom.value = cameraPosition.zoom;
    this.cameraPosition.value = cameraPosition;
    
    // 清除之前的定时器
    _loadDataTimer?.cancel();
    
    // 设置新的定时器，防抖500ms
    _loadDataTimer = Timer(const Duration(milliseconds: 500), () {
      // 检查缩放级别是否达到聚合阈值
      if (currentZoom.value < clusterZoomThreshold) {
        // 聚合模式
        if (!isClusterMode.value) {
          isClusterMode.value = true;
        }
        _loadClusters();
      } else {
        // 普通模式
        if (isClusterMode.value) {
          isClusterMode.value = false;
        }
        _loadStoriesWithinBounds();
      }
    });
  }

  // 获取当前地图边界
  String _getCurrentBounds() {
    if (mapController == null) return '';
    
    // 使用相机位置获取当前地图中心点和缩放级别
    final CameraPosition currentCameraPosition = cameraPosition.value ?? CameraPosition(
      target: currentLocation.value ?? const LatLng(39.9042, 116.4074),
      zoom: currentZoom.value,
    );
    
    final LatLng center = currentCameraPosition.target; // 地图中心点经纬度
    final double zoom = currentCameraPosition.zoom; // 地图缩放级别

    // 计算当前缩放级别下，地图窗口对应的经纬度跨度
    // 基于网络地图瓦片系统原理：
    // - zoom=0时，整个地球360度经度，180度纬度
    // - 每增加1级，地图精度提高2倍，显示范围缩小一半
    // - 手机屏幕宽度约360-414逻辑像素，对应实际地图范围需要经验调整
    
    // 基础计算：360度 / (2^zoom) 得到当前级别的基本跨度
    // 然后考虑手机屏幕显示比例和实际视觉效果进行调整
    double baseDelta = 180.0 / (1 << zoom.toInt());  // 基础跨度（半球）
    
    // 经验系数调整：根据实际测试，当系数为0.3时，范围最接近真实可视区域
    // 这个系数考虑了：屏幕像素密度、地图投影变形、用户视觉感受
    double visualScaleFactor = 2;  // 视觉比例系数（原0.5调整为0.3，扩大1.67倍）
    double delta = baseDelta * visualScaleFactor;

    // 计算西南角（左下）和东北角（右上）的坐标
    final LatLng southwest = LatLng(center.latitude - delta, center.longitude - delta);
    final LatLng northeast = LatLng(center.latitude + delta, center.longitude + delta);

    // 构建LatLngBounds对象
    final LatLngBounds bounds = LatLngBounds(southwest: southwest, northeast: northeast);
    
    // 添加调试日志，帮助验证计算结果
    Get.log('地图边界计算 - 中心点: (${center.latitude}, ${center.longitude}), 缩放级别: $zoom, 跨度: ±${delta.toStringAsFixed(6)}°, 范围: ${(delta * 2).toStringAsFixed(6)}°');
    Get.log('地图边界 - 西南: (${southwest.latitude}, ${southwest.longitude}), 东北: (${northeast.latitude}, ${northeast.longitude})');
    
    // 返回格式：minLat,minLng,maxLat,maxLng
    return '${bounds.southwest.latitude},${bounds.southwest.longitude},${bounds.northeast.latitude},${bounds.northeast.longitude}';
  }

  // 调用聚合API
  Future<void> _loadClusters() async {
    try {
      final bounds = _getCurrentBounds();
      if (bounds.isEmpty) return;
      
      // 获取当前选中的分类
      List<String> selectedCategoryList = [];
      selectedCategories.forEach((category, isSelected) {
        if (isSelected) {
          selectedCategoryList.add(category);
        }
      });
      
      // 记录过滤参数
      Get.log('调用getClusters API - 分类: ${selectedCategoryList.join(',')}, 官方: ${showOfficialOnly.value}, 用户: ${nicknameFilter.value}');
      
      final response = await StoryMapApi.getClusters(
        currentZoom.value.toInt(),
        bounds,
        categories: selectedCategoryList.isNotEmpty ? selectedCategoryList : null,
        isOfficial: showOfficialOnly.value ? true : null,
        nickname: nicknameFilter.value.isNotEmpty ? nicknameFilter.value : null,
      );
      
      if (response.code == 200 || response.code == StatusCode.getSuccess) {
        await _parseClusters(response.data);
      }
    } catch (e) {
      Get.log('加载聚合数据失败: $e');
      // 失败时回退到模拟数据
      await _loadMockData();
    }
  }

  // 调用边界内故事API
  Future<void> _loadStoriesWithinBounds() async {
    try {
      final bounds = _getCurrentBounds();
      if (bounds.isEmpty) return;
      
      // 获取当前选中的分类
      List<String> selectedCategoryList = [];
      selectedCategories.forEach((category, isSelected) {
        if (isSelected) {
          selectedCategoryList.add(category);
        }
      });
      
      // 记录过滤参数
      Get.log('调用getStoriesWithinBounds API - 分类: ${selectedCategoryList.join(',')}, 官方: ${showOfficialOnly.value}, 用户: ${nicknameFilter.value}');
      
      final response = await StoryMapApi.getStoriesWithinBounds(
        bounds,
        categories: selectedCategoryList.isNotEmpty ? selectedCategoryList : null,
        isOfficial: showOfficialOnly.value ? true : null,
        nickname: nicknameFilter.value.isNotEmpty ? nicknameFilter.value : null,
      );
      
      if (response.code == 200 || response.code == StatusCode.getSuccess) {
        await _parseStoriesWithinBounds(response.data);
      }
    } catch (e) {
      Get.log('加载边界内故事失败: $e');
      // 失败时回退到模拟数据
      await _loadMockData();
    }
  }

  // 解析聚合数据
  Future<void> _parseClusters(Map<String, dynamic> data) async {
    List<StoryPin> allPins = [];
    
    // 解析聚合点
    if (data['clusters'] != null) {
      for (var cluster in data['clusters']) {
        // 为每个聚合点创建一个代表点
        final position = cluster['position'] as List;
        allPins.add(StoryPin(
          id: cluster['id'],
          title: '聚合地点 (${cluster['count']}个故事)',
          content: '这里有${cluster['count']}个精彩故事等你发现',
          lat: position[1], // 纬度
          lng: position[0], // 经度
          type: 'cluster',
          noteType: 0,
          isOfficial: false,
          imageUrls: [],
          author: '聚合',
          likes: cluster['count'],
        ));
      }
    }
    
    // 解析独立点
    if (data['singlePoints'] != null) {
      for (var point in data['singlePoints']) {
        final position = point['position'] as List;
        allPins.add(StoryPin(
          id: point['id'],
          title: point['name'] ?? '未知地点',
          content: '一个有趣的地方',
          lat: position[1], // 纬度
          lng: position[0], // 经度
          type: 'single',
          noteType: 0,
          isOfficial: false,
          imageUrls: [],
          author: '聚合',
          likes: 1,
        ));
      }
    }
    
    storyPins.value = allPins;
    // 服务器已根据过滤条件返回结果，直接使用，不再进行客户端过滤
    filteredPins.value = allPins;
    
    // 重置故事预览索引，防止越界
    if (currentStoryIndex.value >= filteredPins.length) {
      currentStoryIndex.value = 0;
    }
    
    await updateMarkers();
  }

  // 解析边界内故事数据
  Future<void> _parseStoriesWithinBounds(Map<String, dynamic> data) async {
    // 假设返回的是分页数据，提取内容列表
    List<dynamic> contentList = [];
    if (data['content'] != null) {
      contentList = data['content'];
    } else if (data['records'] != null) {
      contentList = data['records'];
    } else if (data['list'] != null) {
      contentList = data['list'];
    } else {
      // 如果data没有content、records或list字段，可能是其他格式
      Get.log('边界内故事数据格式未知: $data');
      return;
    }
    
    List<StoryPin> allPins = [];
    for (var item in contentList) {
      allPins.add(_parseStoryPin(item));
    }
    
    storyPins.value = allPins;
    // 服务器已根据过滤条件返回结果，直接使用，不再进行客户端过滤
    filteredPins.value = allPins;
    
    // 重置故事预览索引，防止越界
    if (currentStoryIndex.value >= filteredPins.length) {
      currentStoryIndex.value = 0;
    }
    
    await updateMarkers();
  }

  // 解析单个故事点
  StoryPin _parseStoryPin(Map<String, dynamic> item) {
    return StoryPin(
      id: item['id'].toString(),
      title: item['title'] ?? '无标题',
      content: item['content'] ?? '暂无描述',
      lat: item['latitude']?.toDouble() ?? 0.0,
      lng: item['longitude']?.toDouble() ?? 0.0,
      type: item['belongCategoryName'] ?? 'unknown',
      noteType: item['notesType']??0,
      isOfficial: item['isOfficial'] ?? false,
      imageUrls: item['imageUrls'] != null ? List<String>.from(item['imageUrls']) : [],
      authorId: item['belongUserId'] ?? '0',
      author: item['nickname']??'匿名用户',
      likes: item['likes'] ?? 0,
    );
  }

  // 初始化数据加载
  Future<void> _loadInitialData() async {
    // 先加载分类数据
    await _loadCategories();
    
    // 根据当前缩放级别决定加载方式
    if (currentZoom.value < clusterZoomThreshold) {
      await _loadClusters();
    } else {
      await _loadStoriesWithinBounds();
    }
  }

  // 从API获取分类数据
  Future<void> _loadCategories() async {
    try {
      HttpResponse response = await NoteApi.getNoteCategory();
      if (response.code == StatusCode.getSuccess) {
        List<dynamic> categoryList = response.data as List<dynamic>;
        categories.value = categoryList.map((item) => item as Map<String, dynamic>).toList();
        
        // 动态生成选中状态，默认不选中任何分类（查询全部）
        Map<String, bool> initialSelection = {};
        for (var category in categories) {
          String categoryKey = category['categoryName']?.toString().toLowerCase() ?? 'unknown';
          initialSelection[categoryKey] = false; // 默认不选中
        }
        selectedCategories.value = initialSelection;
        
        Get.log('成功加载分类数据: ${categories.length}个分类');
      } else {
        Get.log('获取分类数据失败: ${response.msg}');
        _useDefaultCategories();
      }
    } catch (e) {
      Get.log('获取分类数据出错: $e');
      _useDefaultCategories();
    }
  }

  // 使用默认分类
  void _useDefaultCategories() {
    categories.value = [
      {'id': 1, 'categoryName': '旅行', 'categorySort': 1},
      {'id': 2, 'categoryName': '美食', 'categorySort': 2},
      {'id': 3, 'categoryName': '咖啡', 'categorySort': 3},
      {'id': 4, 'categoryName': '购物', 'categorySort': 4},
      {'id': 5, 'categoryName': '景点', 'categorySort': 5},
      {'id': 6, 'categoryName': '酒店', 'categorySort': 6},
    ];
    
    selectedCategories.value = {
      'travel': false,
      'food': false,
      'coffee': false,
      'shopping': false,
      'attraction': false,
      'hotel': false,
    };
  }

  Future<BitmapDescriptor> _createMarkerIcon(StoryPin pin) async {
    // 根据pin类型返回不同的图标
    try {
      Get.log('创建标记图标，pin类型: ${pin.type}, ID: ${pin.id}, 标题: ${pin.title}');
      
      // 如果是聚合点，创建动态图标
      if (pin.type == 'cluster') {
        return await _createClusterIcon(pin);
      }else if(pin.type == 'single'){
        return await _createClusterIcon(pin);
      }
      
      // 定义类型到图片文件的映射
      Map<String, String> iconMapping = {
        '默认': 'images/yule.jpg',      // 未知 -> 大师篮球
        '搞笑': 'images/gaoxiao.jpg',
        '鬼故事': 'images/ggs.jpg',
        '记忆': 'images/jiyi.jpg',
        '旅游': 'images/lvyou.jpg',
        '摄影': 'images/sheying.jpg',
        '寻宝': 'images/xunbao.jpg',
        '娱乐': 'images/yule.jpg',
        '历史': 'images/lishi.jpg',
        '艺术': 'images/yishu.jpg',
      };
      
      // 根据pin类型获取对应的图片路径，如果没有映射则使用默认图片
      String imagePath = iconMapping[pin.type] ?? 'images/yule.jpg';
      Get.log('选择的图片路径: $imagePath');
      
      // 使用自定义图标 - 使用异步方式创建
      BitmapDescriptor icon = await BitmapDescriptor.fromAssetImage(
        const ImageConfiguration(size: Size(68, 68)),
        imagePath,
      );
      
      Get.log('图标创建成功: ${pin.type}');
      return icon;
    } catch (e) {
      Get.log('加载自定义标记图标失败: ${pin.type}, 错误: $e');
      // 如果加载失败，返回默认图标
      return BitmapDescriptor.defaultMarker;
    }
  }

  // 创建聚合图标
  Future<BitmapDescriptor> _createClusterIcon(StoryPin pin) async {
    try {
      // 获取聚合数量
      int count = pin.likes;
      // 如果超过99，显示99+
      String displayText = count > 99 ? '99+' : count.toString();
      
      // 创建画布
      final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(pictureRecorder);
      
      // 设置图标大小
      const double size = 80.0;
      
      // 绘制圆形背景
      final ui.Paint backgroundPaint = ui.Paint()
        ..color = Colors.red
        ..style = ui.PaintingStyle.fill;
      canvas.drawCircle(const ui.Offset(size/2, size/2), size/2, backgroundPaint);
      
      // 绘制圆形边框
      final ui.Paint borderPaint = ui.Paint()
        ..color = Colors.white
        ..style = ui.PaintingStyle.stroke
        ..strokeWidth = 3;
      canvas.drawCircle(const ui.Offset(size/2, size/2), size/2 - 1.5, borderPaint);
      
      // 绘制数字
      final TextPainter textPainter = TextPainter(
        text: TextSpan(
          text: displayText,
          style: TextStyle(
            color: Colors.white,
            fontSize: count > 99 ? 24 : 28, // 99+ 使用稍小字体
            fontWeight: FontWeight.bold,
          ),
        ),
        textDirection: TextDirection.ltr,
      );
      
      textPainter.layout();
      final Offset textOffset = Offset(
        (size - textPainter.width) / 2,
        (size - textPainter.height) / 2,
      );
      textPainter.paint(canvas, textOffset);
      
      // 生成图片
      final ui.Picture picture = pictureRecorder.endRecording();
      final ui.Image image = await picture.toImage(size.toInt(), size.toInt());
      final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      
      if (byteData == null) {
        throw Exception('无法生成聚合图标字节数据');
      }
      
      final Uint8List uint8List = byteData.buffer.asUint8List();
      return BitmapDescriptor.fromBytes(uint8List);
    } catch (e) {
      Get.log('创建聚合图标失败: $e');
      // 如果创建失败，返回默认聚合图标
      return await BitmapDescriptor.fromAssetImage(
        const ImageConfiguration(size: Size(48, 48)),
        'images/rsjy.jpg',
      );
    }
  }
  
  // 创建已连接故事的图标
  Future<BitmapDescriptor> _createConnectedStoryIcon(StoryPin pin) async {
    try {
      // 获取连接顺序号
      int order = connectedStoryPins.indexWhere((p) => p.id == pin.id) + 1;
      
      // 创建画布
      final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
      final ui.Canvas canvas = ui.Canvas(pictureRecorder);
      
      // 设置图标大小
      const double size = 68.0;
      
      // 绘制圆形背景（绿色表示已连接）
      final ui.Paint backgroundPaint = ui.Paint()
        ..color = Colors.green
        ..style = ui.PaintingStyle.fill;
      canvas.drawCircle(const ui.Offset(size/2, size/2), size/2, backgroundPaint);
      
      // 绘制圆形边框
      final ui.Paint borderPaint = ui.Paint()
        ..color = Colors.white
        ..style = ui.PaintingStyle.stroke
        ..strokeWidth = 3;
      canvas.drawCircle(const ui.Offset(size/2, size/2), size/2 - 1.5, borderPaint);
      
      // 绘制顺序号
      final TextPainter textPainter = TextPainter(
        text: TextSpan(
          text: order.toString(),
          style: const TextStyle(
            color: Colors.white,
            fontSize: 24,
            fontWeight: FontWeight.bold,
          ),
        ),
        textDirection: TextDirection.ltr,
      );
      
      textPainter.layout();
      final Offset textOffset = Offset(
        (size - textPainter.width) / 2,
        (size - textPainter.height) / 2,
      );
      textPainter.paint(canvas, textOffset);
      
      // 生成图片
      final ui.Picture picture = pictureRecorder.endRecording();
      final ui.Image image = await picture.toImage(size.toInt(), size.toInt());
      final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      
      if (byteData == null) {
        throw Exception('无法生成连接图标字节数据');
      }
      
      final Uint8List uint8List = byteData.buffer.asUint8List();
      return BitmapDescriptor.fromBytes(uint8List);
    } catch (e) {
      Get.log('创建连接图标失败: $e');
      // 如果创建失败，返回绿色默认图标
      return BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen);
    }
  }

  void onMarkerTap(StoryPin pin) {
    // 如果处于故事连接模式
    if (isStoryConnectionMode.value) {
      connectStoryPin(pin);
      return;
    }
    
    // 默认行为：显示故事预览
    showStoryPreview.value = true;
    int index = filteredPins.indexOf(pin);
    // 确保索引有效，如果找不到则默认为0
    currentStoryIndex.value = index >= 0 ? index : 0;
  }

  /**
   * 地图点击事件处理 - 点击地图时关闭所有弹窗
   */
  void onMapTap(LatLng position) {
    Get.log('地图被点击，关闭所有弹窗');
    // 关闭过滤弹窗
    if (showFilterPopup.value) {
      showFilterPopup.value = false;
    }
    // 关闭故事预览弹窗
    if (showStoryPreview.value) {
      showStoryPreview.value = false;
    }
  }

  /**
   * 地图创建完成回调
   */
  void onMapCreated(AMapController controller) {
    mapController = controller;
    Get.log('地图控制器已初始化完成');
    
    // 检查是否有待处理的位置数据
    if (currentLocation.value != null && !hasMovedToLocation.value) {
      // 延迟一下确保地图完全初始化
      Future.delayed(const Duration(milliseconds: 500), () {
        if (mapController != null && currentLocation.value != null) {
          mapController?.moveCamera(
            CameraUpdate.newLatLngZoom(currentLocation.value!, currentZoom.value),
          );
          hasMovedToLocation.value = true;
          Get.log('地图初始化完成后自动移动到当前位置');
        }
      });
    }
  }

  /**
   * 移动到当前位置
   */
  void moveToCurrentLocation() {
    if (currentLocation.value != null && mapController != null) {
      mapController?.moveCamera(
        CameraUpdate.newLatLngZoom(currentLocation.value!, currentZoom.value),
      );
    }
  }

  void toggleFilterPopup() {
    showFilterPopup.value = !showFilterPopup.value;
  }

  Future<void> toggleCategory(String category) async {
    selectedCategories[category] = !(selectedCategories[category] ?? false);
    // 不再立即过滤，只更新选中状态
    Get.log('切换分类选中状态: $category = ${selectedCategories[category]}');
  }

  // 全选所有分类
  void selectAllCategories() {
    selectedCategories.forEach((key, value) {
      selectedCategories[key] = true;
    });
    Get.log('全选所有分类');
  }

  // 清空所有分类选择
  void clearAllCategories() {
    selectedCategories.forEach((key, value) {
      selectedCategories[key] = false;
    });
    Get.log('清空所有分类选择');
  }

  Future<void> toggleOfficialOnly() async {
    showOfficialOnly.value = !showOfficialOnly.value;
    // 不再立即过滤，只更新选中状态
    Get.log('切换官方认证状态: ${showOfficialOnly.value}');
  }

  // 确认过滤条件并重新加载数据
  Future<void> confirmFilterAndReload() async {
    Get.log('确认过滤条件，重新加载数据');
    
    // 关闭弹窗
    showFilterPopup.value = false;
    
    // 根据当前缩放级别重新加载数据
    if (currentZoom.value < clusterZoomThreshold) {
      // 缩放级别较低时，加载聚合数据
      await _loadClusters();
    } else {
      // 缩放级别较高时，加载详细故事数据
      await _loadStoriesWithinBounds();
    }
  }

  void nextStory() {
    if (filteredPins.isEmpty) return;
    if (currentStoryIndex.value < filteredPins.length - 1) {
      currentStoryIndex.value++;
    } else {
      // 如果已经是最后一个，循环到第一个
      currentStoryIndex.value = 0;
    }
  }

  void previousStory() {
    if (filteredPins.isEmpty) return;
    if (currentStoryIndex.value > 0) {
      currentStoryIndex.value--;
    } else {
      // 如果已经是第一个，循环到最后一个
      currentStoryIndex.value = filteredPins.length - 1;
    }
  }

  void closeStoryPreview() {
    showStoryPreview.value = false;
  }

  void navigateToStoryDetail(StoryPin story) {
    int storyId = int.tryParse(story.id) ?? 0;
    story.noteType == 0
        ? Get.toNamed('/notes/detail/image', arguments: storyId)
        : Get.toNamed('/notes/detail/video', arguments: storyId);
  }

  void navigateToUserProfile(String userId) {
    int userIdInt = int.tryParse(userId) ?? 0;
    Get.toNamed('/other/mine', arguments: userIdInt);
  }

  // 选择地点模式相关方法
  void selectLocation(LatLng position) {
    selectedLocation.value = position;
    selectedLocationAddress.value = '纬度: ${position.latitude.toStringAsFixed(6)}, 经度: ${position.longitude.toStringAsFixed(6)}';
    Get.log('已选择地点: ${selectedLocation.value}');
  }

  void confirmLocationSelection() {
    if (selectedLocation.value != null) {
      Get.back(result: {
        'location': selectedLocation.value,
        'address': selectedLocationAddress.value,
      });
    } else {
      Get.snackbar('提示', '请先选择地点');
    }
  }

  void cancelLocationSelection() {
    Get.back();
  }

  // 路线创建相关方法
  void addRouteMarker(LatLng position) {
    if (routeMarkers.length >= maxMarkers) {
      Get.snackbar('提示', '最多只能添加$maxMarkers个地点');
      return;
    }
    
    routeMarkers.add(position);
    updateRouteLines();
    updateRouteMarkers();
    Get.log('添加了路线marker: $position, 当前数量: ${routeMarkers.length}');
    
    // 显示添加成功的提示
    Get.snackbar('提示', '成功添加地点 ${routeMarkers.length}');
  }

  void selectRouteMarker(int index) {
    if (index < 0 || index >= routeMarkers.length) return;
    
    // 如果之前有其他选中的marker，添加连线
    if (selectedMarkerIndex.value != -1 && selectedMarkerIndex.value != index) {
      // 这里可以添加连线的逻辑
    }
    
    selectedMarkerIndex.value = index;
    updateRouteMarkers();
    Get.log('选中了路线marker: $index');
  }

  void removeRouteMarker(int index) {
    if (index < 0 || index >= routeMarkers.length) return;
    
    routeMarkers.removeAt(index);
    if (selectedMarkerIndex.value >= routeMarkers.length) {
      selectedMarkerIndex.value = routeMarkers.length - 1;
    }
    updateRouteLines();
    updateRouteMarkers();
    Get.log('移除了路线marker: $index');
  }

  void clearAllRouteMarkers() {
    routeMarkers.clear();
    selectedMarkerIndex.value = -1;
    routeLines.clear();
    updateRouteMarkers();
    Get.log('清空了所有路线marker');
    
    // 显示清空成功的提示
    Get.snackbar('提示', '已清空所有选择的地点');
  }

  void updateRouteLines() {
    routeLines.clear();
    
    if (routeMarkers.length < 2) return;
    
    for (int i = 0; i < routeMarkers.length - 1; i++) {
      final polyline = Polyline(
        points: [routeMarkers[i], routeMarkers[i + 1]],
        color: Colors.red.withOpacity(0.7),
        width: 3,
      );
      routeLines.add(polyline);
    }
    
    Get.log('更新了路线连线，共${routeLines.length}条');
  }

  void updateRouteMarkers() {
    // 重新生成所有markers，包括路线markers和普通故事markers
    final newMarkers = <Marker>[];
    
    // 添加路线markers
    for (int i = 0; i < routeMarkers.length; i++) {
      final isSelected = i == selectedMarkerIndex.value;
      final marker = Marker(
        position: routeMarkers[i],
        icon: isSelected ? BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed) : BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
        infoWindow: InfoWindow(
          title: '地点 ${i + 1}',
          snippet: isSelected ? '已选中' : '点击选择',
        ),
        onTap: (String id) {
          selectRouteMarker(i);
        },
      );
      newMarkers.add(marker);
    }
    
    // 添加普通故事markers（如果不是在路线创建模式下）
    if (!isRouteCreationMode.value) {
      newMarkers.addAll(markers);
    }
    
    markers.value = newMarkers;
    Get.log('更新了路线marker显示状态，共${newMarkers.length}个markers');
  }

  // 创建普通marker图标
  BitmapDescriptor _createNormalMarkerBitmap() {
    return BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue);
  }

  // 创建选中状态的marker图标
  BitmapDescriptor _createSelectedMarkerBitmap() {
    return BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed);
  }

  void confirmRouteCreation() {
    if (routeMarkers.isEmpty) {
      Get.snackbar('提示', '请先添加路线地点');
      return;
    }
    
    if (routeName.value.isEmpty) {
      Get.snackbar('提示', '请输入路线名称');
      return;
    }
    
    // 返回路线数据
    Get.back(result: {
      'routeName': routeName.value,
      'markers': routeMarkers,
      'lines': routeLines,
    });
  }
  
  // 故事连接相关方法
  
  /// 切换故事连接模式
  void toggleStoryConnectionMode() {
    isStoryConnectionMode.value = !isStoryConnectionMode.value;
    
    if (isStoryConnectionMode.value) {
      // 进入连接模式
      connectedStoryPins.clear();
      routeLines.clear();
      Get.snackbar('连接模式', '请按顺序点击故事marker进行连接，最多连接$maxConnectedStories个');
    } else {
      // 退出连接模式
      Get.snackbar('连接模式', '已退出故事连接模式');
    }
    
    // 更新marker显示
    updateMarkers();
  }
  
  /// 连接故事marker
  void connectStoryPin(StoryPin pin) {
    // 检查是否已经连接过
    if (connectedStoryPins.any((p) => p.id == pin.id)) {
      Get.snackbar('提示', '该故事已经连接过了');
      return;
    }
    
    // 检查连接数量限制
    if (connectedStoryPins.length >= maxConnectedStories) {
      Get.snackbar('提示', '最多只能连接$maxConnectedStories个故事');
      return;
    }
    
    // 添加到连接列表
    connectedStoryPins.add(pin);
    
    // 更新连线
    updateStoryRouteLines();
    
    // 更新marker显示
    updateMarkers();
    
    Get.log('连接了故事: ${pin.title}, 当前连接数: ${connectedStoryPins.length}');
    Get.snackbar('连接成功', '已连接故事: ${pin.title} (${connectedStoryPins.length}/$maxConnectedStories)');
  }
  
  /// 更新故事路线连线
  void updateStoryRouteLines() {
    routeLines.clear();
    
    if (connectedStoryPins.length < 2) return;
    
    // 按连接顺序绘制连线
    for (int i = 0; i < connectedStoryPins.length - 1; i++) {
      final fromPin = connectedStoryPins[i];
      final toPin = connectedStoryPins[i + 1];
      
      final polyline = Polyline(
        points: [
          LatLng(fromPin.lat, fromPin.lng),
          LatLng(toPin.lat, toPin.lng)
        ],
        color: Colors.green.withOpacity(0.8),
        width: 4,
      );
      routeLines.add(polyline);
    }
    
    Get.log('更新了故事路线连线，共${routeLines.length}条');
  }
  
  /// 移除连接的故事
  void removeConnectedStory(StoryPin pin) {
    connectedStoryPins.removeWhere((p) => p.id == pin.id);
    updateStoryRouteLines();
    updateMarkers();
    Get.log('移除了连接的故事: ${pin.title}');
  }
  
  /// 清空所有连接的故事
  void clearAllConnectedStories() {
    connectedStoryPins.clear();
    routeLines.clear();
    updateMarkers();
    Get.snackbar('提示', '已清空所有连接的故事');
  }
  
  /// 保存故事路线
  Future<void> saveStoryRoute() async {
    if (connectedStoryPins.length < 2) {
      Get.snackbar('提示', '请至少连接两个故事');
      return;
    }
    
    if (routeName.value.isEmpty) {
      Get.snackbar('提示', '请输入路线名称');
      return;
    }
    
    try {
      // 准备故事数据
      List<Map<String, dynamic>> storyData = connectedStoryPins.map((pin) => {
        'id': pin.id,
        'title': pin.title,
        'content': pin.content,
        'latitude': pin.lat,
        'longitude': pin.lng,
        'type': pin.type,
        'author': pin.author,
        'authorId': pin.authorId,
        'likes': pin.likes,
        'imageUrls': pin.imageUrls,
      }).toList();
      
      // 准备连接数据
      List<Map<String, dynamic>> connections = [];
      for (int i = 0; i < connectedStoryPins.length - 1; i++) {
        connections.add({
          'from': i,
          'to': i + 1,
          'fromStoryId': connectedStoryPins[i].id,
          'toStoryId': connectedStoryPins[i + 1].id,
          'order': i + 1,
        });
      }
      
      // 获取用户ID
      User userInfo = User.fromJson(
        jsonDecode(await readData('userInfo') ?? jsonEncode(DefaultData.user))
      );
      int userId = userInfo.id;
      
      // 调用API保存
      final response = await NoteApi.saveStoryRoute(
        routeName: routeName.value,
        stories: storyData,

        userId: userId,
        description: '用户创建的故事路线',
        routeColor: "#4CAF50", // 绿色，表示故事路线
        lineWidth: 4, // 与UI中的连线宽度保持一致
        tags: ['故事路线', '用户创建'],
      );
      
      if (response.code == 200 || response.code == StatusCode.postSuccess) {
        Get.snackbar('成功', '故事路线保存成功！');
        Get.log('保存的故事路线: ${routeName.value}, 包含${connectedStoryPins.length}个故事');
      } else {
        Get.snackbar('错误', response.msg.isEmpty ? '保存失败，请重试' : response.msg);
        return;
      }
      
      // 返回结果
      Get.back(result: {
        'routeName': routeName.value,
        'stories': storyData,
        'connections': connections,
        'saved': true,
      });
      
    } catch (e) {
      Get.log('保存故事路线失败: $e');
      Get.snackbar('错误', '保存失败，请重试');
    }
  }
}

class StoryPin {
  final String id;
  final String title;
  final String content;
  final double lat;
  final double lng;
  final String type;
  final int noteType;
  final bool isOfficial;
  final List<String> imageUrls;
  final String author;
  final int likes;
  final String? authorAvatar;
  final String? authorId;

  StoryPin({
    required this.id,
    required this.title,
    required this.content,
    required this.lat,
    required this.lng,
    required this.type,
    required this.noteType,
    required this.isOfficial,
    required this.imageUrls,
    required this.author,
    required this.likes,
    this.authorAvatar,
    this.authorId,
  });
}